#include "socket.hpp"
#include "Log.hpp"
#include <poll.h>
#include <memory>
#include <cstring>
#include <cerrno>
#include <vector>
using namespace SocketModule;
using namespace LogModule;
class poll_server
{
static const int NUM = sizeof(fd_set) * 8;
public:
    poll_server()
        :_listen_sock(std::make_shared<TcpSocket>())
        ,_is_running(false)
        ,fds(NUM, {-1, 0, 0})
    {}

    void init(int port)
    {
        _listen_sock->BuildTcpSocketMethod(port);
        fds[0].fd = _listen_sock->Fd();
        fds[0].events |= POLLIN;
    }

    void loop()
    {
        _is_running = true;
        int listenfd = _listen_sock->Fd();
        int timeout = 2000;
        while(_is_running)
        {
            int ret = poll(fds.data(), fds.size(), timeout);
            if(ret == -1)
            {
                LOG(LogLevel::ERROR) << "Error message: " << strerror(ret);
                continue;
            }
            else if(ret == 0)
            {
                LOG(LogLevel::INFO) << "Time out\n";
                continue;
            }
            else
            {
                LOG(LogLevel::INFO) << "Dispatch begin\n";
                dispatcher();
            }
        }  
    }
    void accepter(int fd)
    {
        InetAddr client;
        auto client_sock = _listen_sock->Accepter(&client);
        if(client_sock == nullptr)
        {
            LOG(LogLevel::ERROR) << "Accept error";
            return;
        }
        int client_fd = client_sock->Fd();
        if(client_fd < 0)
        {
            LOG(LogLevel::ERROR) << "Client fd error";
            return;
        }
        //将client_fd加入到fds中
        //如果fds满了，关闭连接
        int i=0;
        for(i=0;i<NUM;++i)
        {
            if(fds[i].fd == -1)
            {
                fds[i].fd = client_fd;
                fds[i].events |= POLLIN;
                LOG(LogLevel::INFO) << "Accept success: " << client_sock->Fd() << " " << client.Addr();
                break;
            }
        }
        if(i == NUM)
        {
            //扩容
            LOG(LogLevel::ERROR) << "fds is full";
            fds.resize(NUM * 2, {-1, 0, 0});            

            return;
        }
    }


    void recver(int who)
    {
        int fd = fds[who].fd;
        std::string buffer;
        auto client_sock = std::make_shared<TcpSocket>(fd);
        ssize_t ret = client_sock->Recv(&buffer);
        if(ret == -1)
        {
            LOG(LogLevel::ERROR) << "Recv error" << strerror(errno);
            client_sock->Close();
            //将fd从fds中删除
            fds[who].fd = -1;
            fds[who].events = 0;
            fds[who].revents = 0;
            return;
        }
        else if(ret == 0)
        {
            LOG(LogLevel::INFO) << "Client closed: " << client_sock->Fd();
            client_sock->Close();
            //将fd从fds中删除
            fds[who].fd = -1;
            fds[who].events = 0;
            fds[who].revents = 0;
            return;
        }
        else
        {
            LOG(LogLevel::INFO) << "Recv success: " << buffer;
            return;
        }
    }

    void dispatcher()
    {
        //找到所有合法的fd，分发
        for(int i=0;i<NUM;++i)
        {
            if(fds[i].fd == -1)
                continue;
            if(fds[i].revents & POLLIN)
            {
                //分发给处理连接的函数
                if(fds[i].fd == _listen_sock->Fd())
                {
                    accepter(fds[i].fd);
                }
                //分发给处理IO的函数
                else
                {
                    recver(i);
                }
            }
        }
    }

    void stop()
    {}
private:
    std::shared_ptr<TcpSocket> _listen_sock;
    std::vector<pollfd> fds;
    bool _is_running;
};
